﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Common.Threads
{
    public abstract class WaitHelper
    {
        protected int totalQty = 0;
        protected int successQty = 0;
        private static object lockWaitObj = new object();
        /// <summary>
        /// 将方法组都进行异步执行,并且可通过ContinueWhenAny/All方法进行线程阻塞
        /// </summary>
        /// <param name="acts"></param>
        public virtual void Wait(params Action[] acts)
        {
            Wait(0, acts);
        }
        /// <summary>
        /// 在指定最大线程数下降方法组进行异步执行,并且可通过ContinueWhenAny/All方法进行线程阻塞
        /// </summary>
        /// <param name="MaxThread">最大线程数,小于等于0时,不进行限制</param>
        /// <param name="acts"></param>
        public virtual void Wait(int MaxThread, params Action[] acts)
        {
            totalQty = acts.Length;
            successQty = 0;

            int invokeThread = 0;
            foreach (Action act in acts)
            {
                act.BeginInvoke((c) =>
                {
                    lock (lockWaitObj)
                    {
                        successQty++;
                    }
                }, null);
                //指定最大线程数大于0时,进行当前开启线程数判断
                if (MaxThread > 0)
                {
                    invokeThread++;
                    //正在执行线程大于指定最大线程时,进行线程阻塞
                    while (invokeThread - successQty >= MaxThread)
                    {
                        Thread.Sleep(100);
                    }
                }
            }
        }
        /// <summary>
        /// 当有一个方法执行完成后才能继续执行
        /// </summary>
        /// <param name="act"></param>
        public virtual void ContinueWhenAny(Action act = null)
        {
            if (totalQty > 0)
            {
                while (successQty == 0)
                {
                    Thread.Sleep(100);
                }
                if (act != null)
                    act.BeginInvoke(null, null);
            }
        }
        /// <summary>
        /// 当所有的方法都执行完成后才能继续执行
        /// </summary>
        /// <param name="act"></param>
        public virtual void ContinueWhenAll(Action act = null)
        {
            if (totalQty > 0)
            {
                while (successQty < totalQty)
                {
                    Thread.Sleep(100);
                }
                if (act != null)
                    act.BeginInvoke(null, null);
            }
        }
    }
}
